package editor;

import java.awt.Color;
import java.awt.Toolkit;

import javax.swing.JEditorPane;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import editor.manager.WorkSpaceManager;
import editor.syntaxhighlighter.JavaEditorKit;

/**
 * The base for the text-area. Adds syntax highlighting, line numbers and bracket matching.
 *
 * @author Mark Dessain
 */
@SuppressWarnings("serial")
public class JavaEditorPane extends JEditorPane implements UndoableEditListener
{
	
	protected UndoManager undoManager = new UndoManager();
	private boolean changed = false;
	
	/**
	 * Sets up a new JavaEditorPane.
	 */
	public JavaEditorPane()
	{
		super();
		setEditorKit(new JavaEditorKit(this));
		getDocument().addUndoableEditListener(this);
		setBackground(Color.WHITE);
		undoManager.setLimit(1500);
	}
	
	/**
	 * @param index position in the text-area
	 * @return the line number which that index is on
	 */
	public int getLine(int index)
	{
    	Document doc = getDocument();
    	Element root = doc.getDefaultRootElement();
    	return root.getElementIndex(index);
	}
	
	/**
	 * @param line requests focus on the line
	 */
	public void selectLine(int line)
	{
    	Document doc = getDocument();
    	Element root = doc.getDefaultRootElement();
    	
    	int lineStart = root.getElement(line - 1).getStartOffset();
    	int lineEnd = root.getElement(line - 1).getEndOffset();
    	
    	requestFocus();
    	setSelectionStart(lineStart);
    	setSelectionEnd(lineEnd - 1);
	}
	
	/* (non-Javadoc)
	 * @see javax.swing.event.UndoableEditListener#undoableEditHappened(javax.swing.event.UndoableEditEvent)
	 */
	@Override
	public void undoableEditHappened(UndoableEditEvent e) 
	{
		if(WorkSpaceManager.textAreaManager != null && WorkSpaceManager.textAreaManager.getSelectedIndex() > -1 && !changed)
		{
			WorkSpaceManager.textAreaManager.setSelectedChanged(this);
		}
	
		undoManager.addEdit(e.getEdit());		
	}
	
	/**
	 * Undo an action
	 */
	public void undo()
	{
        try 
        {
            undoManager.undo(); 
            undoManager.undo();
            undoManager.undo();  
        } 
        catch(CannotUndoException cue) 
        { 
            Toolkit.getDefaultToolkit().beep(); 
        } 
	}
	
	/**
	 * Redo an action
	 */
	public void redo()
	{
        try 
        { 
        	undoManager.redo(); 
        	undoManager.redo(); 
        	undoManager.redo(); 
        } 
        catch(CannotRedoException cue) 
        { 
            Toolkit.getDefaultToolkit().beep(); 
        } 
	}
	
	/**
	 * @return True if can undo or redo, False otherwise
	 */
	public boolean canUndoorRedo()
	{
		return undoManager.canUndoOrRedo();
	}
	
	/**
	 * Clears the undo and redo stack
	 */
	public void resetUndoManager()
	{
		changed = false;
		undoManager.die();
		undoManager.discardAllEdits();
	}
	
	/**
	 * @return True if the document has changed since loading, False otherwise
	 */
	public boolean getChanged()
	{
		return changed;
	}
	
	/**
	 * @param bool set the value of whether the document has been changed
	 */
	public void setChanged(boolean bool)
	{
		changed = bool;
	}
}
